package com.yifang.yibingproject.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifang.yibingproject.dto.StaffEditDTO;
import com.yifang.yibingproject.dto.SysMenuDTO;
import com.yifang.yibingproject.dto.SysMenuTreeDTO;
import com.yifang.yibingproject.entity.SysMenuEntity;
import com.yifang.yibingproject.entity.SysRoleMenuEntity;
import com.yifang.yibingproject.exception.ServiceException;
import com.yifang.yibingproject.mapper.SysMenuMapper;
import com.yifang.yibingproject.mapper.SysRoleMenuMapper;
import com.yifang.yibingproject.service.SysMenuService;
import com.yifang.yibingproject.service.SysUserService;
import com.yifang.yibingproject.utils.EntityUtils;
import com.yifang.yibingproject.utils.StringUtilOwn;
import com.yifang.yibingproject.utils.SystemContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenuEntity> implements SysMenuService {
    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    public static  final Long ROLE_MANAGER = 1l;

    @Override
    public String add(SysMenuDTO menu) {
        checkPath(menu.getParentId(), menu.getPath());
        checkParent(menu.getParentId());
        SysMenuEntity entity = EntityUtils.init(new SysMenuEntity());
        BeanUtils.copyProperties(menu, entity);
        //获取该层级的数量
        QueryWrapper<SysMenuEntity> wrapper = Wrappers.query();
        wrapper.eq("parent_id", menu.getParentId());
        int count = count(wrapper);
        entity.setSortIndex(count + 1);
        save(entity);
        SysRoleMenuEntity roleMenu = EntityUtils.init(new SysRoleMenuEntity());
        roleMenu.setMenuId(entity.getId());
        roleMenu.setRoleId(ROLE_MANAGER);
        sysRoleMenuMapper.insert(roleMenu);
        return String.valueOf(entity.getId());
    }

    @Override
    public List<SysMenuTreeDTO> listMy(Integer type) {
        StaffEditDTO staff = sysUserService.updateStaffpage(SystemContext.getCurrentUserId());
        List<SysMenuTreeDTO> dtoList = new ArrayList<>();
        QueryWrapper<SysRoleMenuEntity> wrapper = Wrappers.query();
        wrapper.select("menu_id");
        List<Long> roleIdList = staff.getRoleIdList();
        if (CollectionUtils.isEmpty(roleIdList)) {
            return dtoList;
        }
        int i = 1;
        for (Long roleId : roleIdList) {
            wrapper.eq("role_id", roleId);
            if (i < roleIdList.size()) {
                wrapper.or();
                i++;
            }
        }
        List<SysRoleMenuEntity> roleMenuList = sysRoleMenuMapper.selectList(wrapper);
        List<Long> idList = new ArrayList<>();
        for (SysRoleMenuEntity entity : roleMenuList) {
            idList.add(entity.getMenuId());
        }
        if (CollectionUtils.isEmpty(idList)) {
            return dtoList;
        }
        QueryWrapper<SysMenuEntity> menuWrapper = Wrappers.query();
        menuWrapper.in("id", idList);
        List<SysMenuEntity> list = list(menuWrapper);
        if (!list.isEmpty()) {
            List<SysMenuEntity> subList = list.stream().filter(cate -> "root".equals(cate.getParentId())).collect(Collectors.toList());
            if (!subList.isEmpty()) {
                list.removeAll(subList);
                for (SysMenuEntity root : subList) {
                    SysMenuTreeDTO dto = new SysMenuTreeDTO();
                    BeanUtils.copyProperties(root, dto);
                    dtoList.add(dto);
                    setChildren(dto, list);
                }
            }
        }
        //直接在这里添加我们的排序规则
        Collections.sort(dtoList, new Comparator<SysMenuTreeDTO>() {
            public int compare(SysMenuTreeDTO arg0, SysMenuTreeDTO arg1) {
                return arg0.getSortIndex().compareTo(arg1.getSortIndex());
            }
        });

        return dtoList;
    }


    @Override
    public String del(String id) {
        SysMenuEntity entity = checkEntity(id);
        // 验证分类下是否有子菜单
        QueryWrapper<SysMenuEntity> wrapper = Wrappers.query();
        wrapper.eq("parent_id", id);
        int count = count(wrapper);
        if (count > 0) {
            throw new ServiceException("该分类下有子菜单，不能删除");
        }

        // 删除分类
        UpdateWrapper<SysMenuEntity> updateWrapper = Wrappers.update();
        updateWrapper.set("is_deleted", true);
        updateWrapper.set("update_by", SystemContext.getCurrentUserId());
        updateWrapper.eq("id", id);
        update(updateWrapper);
        return id;
    }

    @Override
    public Page<SysMenuDTO> list(Integer pageNo, Integer pageSize, String parentId) {
        Page<SysMenuEntity> page = new Page<>(pageNo, pageSize);
        QueryWrapper<SysMenuEntity> wrapper = Wrappers.query();
        wrapper.orderByAsc("sort_index");
        wrapper.eq("is_deleted", false);
        if (StringUtilOwn.notEmpty(parentId)) {
            wrapper.eq("parent_id", parentId);
        }
        page = page(page, wrapper);
        Page<SysMenuDTO> dtoPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        if (!CollectionUtils.isEmpty(page.getRecords())) {
            List<SysMenuDTO> dtoList = new ArrayList<>();
            for (SysMenuEntity entity : page.getRecords()) {
                SysMenuDTO dto = new SysMenuDTO();
                BeanUtils.copyProperties(entity, dto);
                dtoList.add(dto);
            }
            dtoPage.setRecords(dtoList);
        }
        return dtoPage;
    }





    /**
     * 获取所有的菜单ID
     * @return
     */
    @Override
    public Set<Long> getAllMenuIdSet() {
        List<SysMenuEntity> list = list();
        Set<Long> ids = list.stream().map(SysMenuEntity::getId).collect(Collectors.toSet());
        return ids;
    }

    /**
     * 根据ID集合获取菜单集合
     * @param ids
     * @return
     */
    @Override
    public List<SysMenuEntity> getMenuByIds(Set<Long> ids) {
        if(ids == null || ids.isEmpty()){
            return new ArrayList<>();
        }
        QueryWrapper<SysMenuEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id",ids);

        List<SysMenuEntity> list = list(queryWrapper);
        return list;
    }

    @Override
    public SysMenuDTO get(String id) {
        SysMenuEntity entity = getById(id);
        if (entity != null) {
            SysMenuDTO dto = new SysMenuDTO();
            BeanUtils.copyProperties(entity, dto);
            return dto;
        }
        return null;
    }

    @Override
    public List<SysMenuTreeDTO> listTree(Integer type) {
        List<SysMenuTreeDTO> dtoList = new ArrayList<>();
        QueryWrapper<SysMenuEntity> wrapper = Wrappers.query();
        wrapper.eq("is_deleted", false);
        List<SysMenuEntity> list = list(wrapper);
        if (!list.isEmpty()) {
            List<SysMenuEntity> subList = list.stream().filter(cate -> "root".equals(cate.getParentId())).collect(Collectors.toList());
            if (!subList.isEmpty()) {
                list.removeAll(subList);
                for (SysMenuEntity root : subList) {
                    SysMenuTreeDTO dto = new SysMenuTreeDTO();
                    BeanUtils.copyProperties(root, dto);
                    dtoList.add(dto);
                    setChildren(dto, list);
                }
            }
        }
        //直接在这里添加我们的排序规则
        Collections.sort(dtoList, new Comparator<SysMenuTreeDTO>() {
            public int compare(SysMenuTreeDTO arg0, SysMenuTreeDTO arg1) {
                return arg0.getSortIndex().compareTo(arg1.getSortIndex());
            }
        });
        return dtoList;
    }

    @Override
    public String update(SysMenuDTO dto) {
        SysMenuEntity entity = getById(dto.getId());
        if (entity == null) {
            throw new ServiceException("菜单不存在");
        }
        if (!entity.getParentId().equals(dto.getParentId()) || !entity.getPath().equals(dto.getPath())) {
            checkPath(dto.getParentId(), dto.getPath());
        }
        if (!entity.getParentId().equals(dto.getParentId())) {
            checkParent(dto.getParentId());
        }
        BeanUtils.copyProperties(dto, entity);
        entity.setUpdateBy(SystemContext.getCurrentUserId());
        updateById(entity);
        return String.valueOf(dto.getId());
    }

    @Override
    public String up(String id) {
        SysMenuEntity current = checkEntity(id);
        QueryWrapper<SysMenuEntity> wrapper = Wrappers.query();
        wrapper.eq("parent_id", current.getParentId());
        wrapper.orderByAsc("sort_index");
        List<SysMenuEntity> entityList = list(wrapper);
        for (int i = 0; i < entityList.size(); i++) {
            SysMenuEntity entity = entityList.get(i);
            if (current.getId().equals(entity.getId()) && i != 0) {
                entityList.set(i, entityList.get(i - 1));
                entityList.set(i - 1, current);
                break;
            }
        }
        for (int i = 0; i < entityList.size(); i++) {
            entityList.get(i).setSortIndex(i + 1);
        }
        updateBatchById(entityList);
        return id;
    }

    @Override
    public String down(String id) {
        SysMenuEntity current = checkEntity(id);
        QueryWrapper<SysMenuEntity> wrapper = Wrappers.query();
        wrapper.eq("parent_id", current.getParentId());
        wrapper.orderByAsc("sort_index");
        List<SysMenuEntity> entityList = list(wrapper);
        for (int i = 0; i < entityList.size(); i++) {
            SysMenuEntity entity = entityList.get(i);
            if (current.getId().equals(entity.getId()) && i != entityList.size() - 1) {
                entityList.set(i, entityList.get(i + 1));
                entityList.set(i + 1, current);
                break;
            }
        }
        for (int i = 0; i < entityList.size(); i++) {
            entityList.get(i).setSortIndex(i + 1);
        }
        updateBatchById(entityList);
        return id;
    }

    @Override
    public List<SysMenuDTO> getParent(String id) {
        List<SysMenuDTO> list = new ArrayList<>();
        return getParentById(list, id);
    }

    @Override
    public String setHidden(String id, Boolean hidden) {
        SysMenuEntity entity = getById(id);
        if (entity == null) {
            throw new ServiceException("菜单不存在");
        }
        entity.setHidden(hidden);
        entity.setUpdateBy(SystemContext.getCurrentUserId());
        updateById(entity);
        return id;
    }

    private List<SysMenuDTO> getParentById(List<SysMenuDTO> list, String id) {
        SysMenuEntity entity = getById(id);
        if (entity != null) {
            SysMenuDTO dta = new SysMenuDTO();
            dta.setTitle(entity.getTitle());
            dta.setId(entity.getId());
            list.add(0, dta);
            getParentById(list, entity.getParentId());
        }
        return list;
    }

    private void setChildren(SysMenuTreeDTO parent, List<SysMenuEntity> list) {
        List<SysMenuTreeDTO> dtoList = new ArrayList<>();
        parent.setChildren(dtoList);
        List<SysMenuEntity> subList = list.stream().filter(cate -> parent.getId().equals(cate.getParentId())).collect(Collectors.toList());
        if (!subList.isEmpty()) {
            list.removeAll(subList);
            for (SysMenuEntity entity : subList) {
                SysMenuTreeDTO dto = new SysMenuTreeDTO();
                BeanUtils.copyProperties(entity, dto);
                dtoList.add(dto);
                //直接在这里添加我们的排序规则
                Collections.sort(dtoList, new Comparator<SysMenuTreeDTO>() {
                    public int compare(SysMenuTreeDTO arg0, SysMenuTreeDTO arg1) {
                        return arg0.getSortIndex().compareTo(arg1.getSortIndex());
                    }
                });
                setChildren(dto, list);
            }
        }
    }

    private void checkPath(String parentId, String path) {
        QueryWrapper<SysMenuEntity> wrapper = Wrappers.query();
        wrapper.eq("parent_id", parentId);
        wrapper.eq("path", path);
        wrapper.last("limit 1");
        SysMenuEntity one = getOne(wrapper);
        if (one != null && one.getPath().equals(path)) {
            throw new ServiceException("菜单路径已存在");
        }
    }

    private void checkParent(String parentId) {
        if (!"root".equals(parentId)) {
            SysMenuEntity parent = getById(parentId);
            if (parent == null) {
                throw new ServiceException("父级菜单不存在");
            }
        }
    }

    private SysMenuEntity checkEntity(String id) {
        SysMenuEntity entity = getById(id);
        if (entity == null) {
            throw new ServiceException("菜单不存在");
        }
        return entity;
    }

}
